package com.meiyuetao.myt.sys.entity;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.audit.SaveUpdateAuditListener;
import lab.s2jh.core.entity.BaseEntity;
import lab.s2jh.core.entity.def.DynamicParameterTypeEnum;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.GenericGenerator;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

@Entity
@Table(name = "T_SYS_DYNA_PROP_LINE_VAL")
@Cache(usage = CacheConcurrencyStrategy.NONE)
@EntityListeners({ SaveUpdateAuditListener.class })
public class DynaPropLineVal extends BaseEntity<Long> implements Comparable<DynaPropLineVal> {
    private static final long serialVersionUID = 1L;
    private Long id;
    /**
     * 值对象名称，如Box，Commodity
     */
    private String objName;
    /**
     * 值对象对应SID主键
     */
    private Long objSid;
    /**
     * 对应属性定义
     */
    private DynaPropLine dynaPropLine;
    /**
     * 值抓取策略：CURRENT("只从当前"), DEFINE("只从定义"), SMART("就近原则");
     */
    private DynaPropValFetchStrategyEnum propValFetchStrategy = DynaPropValFetchStrategyEnum.SMART;
    /**
     * 相对排序号，数字越大越靠上显示 对于某些下拉框类型的数据如果需要关心显示的顺序可通过此参数控制
     */
    private Integer orderRank = 10;
    /**
     * 设定参数值，与propValFetchStrategy配合使用
     */
    private String propVal;
    /**
     * 扩展参数1值，与propValFetchStrategy配合使用
     */
    private String propValExt1;
    /**
     * 扩展参数2值，与propValFetchStrategy配合使用
     */
    private String propValExt2;
    /** 所属父项 */
    private DynaPropLineVal parent;
    /** 下属子项集合 */
    private List<DynaPropLineVal> children;
    /** 配置停用 */
    private Boolean disabled = Boolean.FALSE;

    public enum DynaPropValFetchStrategyEnum {
        @MetaData("只从当前")
        CURRENT, @MetaData("只从定义")
        DEFINE, @MetaData("就近原则")
        SMART;

    }

    @Column(length = 128, nullable = false)
    public String getObjName() {
        return objName;
    }

    public void setObjName(String objName) {
        this.objName = objName;
    }

    @Column(nullable = false)
    public Long getObjSid() {
        return objSid;
    }

    public void setObjSid(Long objSid) {
        this.objSid = objSid;
    }

    @OneToOne
    @JoinColumn(name = "PROP_LINE_SID", nullable = false)
    public DynaPropLine getDynaPropLine() {
        return dynaPropLine;
    }

    public void setDynaPropLine(DynaPropLine dynaPropLine) {
        this.dynaPropLine = dynaPropLine;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "PARENT_sid")
    @JsonIgnore
    public DynaPropLineVal getParent() {
        return parent;
    }

    public void setParent(DynaPropLineVal parent) {
        this.parent = parent;
    }

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy("orderRank desc")
    @JsonIgnore
    public List<DynaPropLineVal> getChildren() {
        return children;
    }

    public void setChildren(List<DynaPropLineVal> children) {
        this.children = children;
    }

    public Integer getOrderRank() {
        return orderRank;
    }

    public void setOrderRank(Integer orderRank) {
        this.orderRank = orderRank;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 16)
    @JsonProperty
    public DynaPropValFetchStrategyEnum getPropValFetchStrategy() {
        return propValFetchStrategy;
    }

    public void setPropValFetchStrategy(DynaPropValFetchStrategyEnum propValFetchStrategy) {
        this.propValFetchStrategy = propValFetchStrategy;
    }

    @Lob
    public String getPropVal() {
        return propVal;
    }

    public void setPropVal(String propVal) {
        this.propVal = propVal;
    }

    @Transient
    public Set<String> getPropValueDisplay() {
        if (StringUtils.isBlank(propVal)) {
            return null;
        }
        Set<String> propValSet = new HashSet<String>();
        if (DynamicParameterTypeEnum.OGNL_LIST.equals(dynaPropLine)) {
            for (String pv : propVal.split(",")) {
                if (pv != null && pv.trim().length() > 0) {
                    propValSet.add(pv.trim());
                }
            }
        } else {
            propValSet.add(propVal);
        }
        return propValSet;
    }

    @Lob
    public String getPropValExt1() {
        return propValExt1;
    }

    public void setPropValExt1(String propValExt1) {
        this.propValExt1 = propValExt1;
    }

    @Lob
    public String getPropValExt2() {
        return propValExt2;
    }

    public void setPropValExt2(String propValExt2) {
        this.propValExt2 = propValExt2;
    }

    public Boolean getDisabled() {
        return disabled;
    }

    public void setDisabled(Boolean disabled) {
        this.disabled = disabled;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((dynaPropLine == null) ? 0 : dynaPropLine.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        DynaPropLineVal other = (DynaPropLineVal) obj;
        if (dynaPropLine.getId() == null) {
            if (other.dynaPropLine.getId() != null)
                return false;
        } else if (!dynaPropLine.getId().equals(other.dynaPropLine.getId()))
            return false;
        return true;
    }

    @Id
    @Column(name = "sid")
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "native")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    @Transient
    public String getDisplay() {

        return objName;
    }

    @Override
    public int compareTo(DynaPropLineVal o) {
        return CompareToBuilder.reflectionCompare(o.getOrderRank(), this.getOrderRank());
    }

}